#pragma once

#include "resolve_type.h"
#include "nef_log.h"

namespace nef {

class Catalog;


template<typename Trait>
struct auto_register_resolver
{
	static void Resolve(Catalog &cat) { }
};

template<typename Type, typename IxType, const char *ContractName, typename scope>
struct auto_register_resolver<nef_export<Type, IxType, ContractName, scope>>
{
	static void Resolve(Catalog &cat)
	{
		cat.Register<nef_export<Type, IxType, ContractName, scope>>();
	}
};

template<typename T, typename Trait>
void auto_register_export(Catalog &cat)
{
	nef_out << "Found Export '" << typeid(Trait).name() << nef_line;
	auto_register_resolver<Trait>::Resolve(cat);
}

#define PP_DECLARE_AUTO_REGISTER(z, n, rtype) \
	\
	template<typename Trait, typename T, bool val> \
struct auto_register_ ## rtype ## _ ## n ## _t \
{ \
	template<typename CT> static void Resolve(CT &c) { } \
}; \
	\
	template<typename Trait, typename T> \
struct auto_register_ ## rtype ## _ ## n ## _t<Trait, T, true> \
{ \
	template<typename CT> \
	static void Resolve(CT &c) \
{ \
	auto_register_ ## rtype<T, typename Trait::rtype ## n>(c); \
} \
}; \
	\
	template<typename Trait, typename T = Trait> \
struct auto_register_ ## rtype ## _ ## n \
	: auto_register_ ## rtype ## _ ## n ## _t<Trait, T, has_ ## rtype ## n ## _test<Trait>::value> \
{}; 

BOOST_PP_REPEAT(MAX_EXPORTS, PP_DECLARE_AUTO_REGISTER, export)

#define PP_AUTO_REGISTER(z, C, rtype) auto_register_ ## rtype ## _ ## C<T>::Resolve(cat);
#define PP_AUTO_REGISTER_T(z, C, rtype) auto_register_ ## rtype ## _ ## C<nef_traits<T>, T>::Resolve(cat);

template<typename T>
void auto_register(Catalog &cat)
{
	static bool ALREADY_REGISTERED = false;

	if (ALREADY_REGISTERED)
		return;

	nef_out << "Auto-Registering '" << typeid(T).name() << "'" << nef_line;

	BOOST_PP_REPEAT(MAX_EXPORTS, PP_AUTO_REGISTER, export)
	BOOST_PP_REPEAT(MAX_EXPORTS, PP_AUTO_REGISTER_T, export)

	//BOOST_PP_REPEAT(MAX_EXPORTS, PP_RESOLVE, auto_export)
	//BOOST_PP_REPEAT(MAX_EXPORTS, PP_RESOLVE_T, auto_export)

	ALREADY_REGISTERED = true;
	
}

}